package learn.up.java.thread;

/**
 * java内存模型  java Memory Model:描述了java中各种变量(线程共享变量)
 * 的访问规则，以及在JVM中将变量存储到内存和从内存中读取变量这样的细节
 * 1.所有变量都存储在主内存中
 * 2.每个线程都有自己的独立工作内存，里面保存该线程使用到的变量的副本
 *    (主内存中该变量的一份拷贝 )
 * 3.线程对共享变量的操作都只能在自己的工作内存中进行，而不能在直接从
 *    主内存中进行读写
 * 4.不同内存间不能直接访问其他线程工作内存中的变量，线程间变量值的传递
 *    需要通过主内存来完成
 *    
 *  实现共享变量的内存可见性，必须保证两点：
 *  1.线程修改后的共享变量值能够及时更新到主内存中
 *  2.其他线程能够及时从主内存中把共享变量的最新值更新到自己的工作内存中
 *  语言层面实现内存可见性的方法：
 *     synchronized   和volatile
 *     JVM关于synchronized的两个规定
 * 1.线程解锁前，必须把共享变量的最新值更新到主内存中去
 * 2.线程加锁时，先清空工作内存中共享变量的值，使用共享变量时从主内存中读取
 * 最新值，（注意：加锁解锁必须是同一把锁）
 * 
 * volatile:可以保证变量的可见性：
 *     读取前后会根据指令去清空工作内存的变量值，从主内存读取最新值
 * 
 *  不能保证volatile变量复合操作的原子性
 * 
 * 线程执行互斥代码的过程：
 * 1.获得互斥锁
 * 2.清空工作内存
 * 3.从主内存中拷贝共享变量最新值的副本
 * 4.执行代码
 * 5.将操作后的共享变量更新到主内存
 * 6.释放锁
 * 
 * 指令重排序：
 *    代码书写的顺序与实际执行顺序不同，指令重排序是编译器或处理器为提高程序性
 *  能而做的优化，有几种重排序方式
 *  1.编译器优化重排序（编译器优化）
 *  2.指令级并行的重排序(处理器优化)
 *  3.内存系统的重排序(处理器优化	)
 *  
 * as-if-serial 语义：
 *    无论如何重排序，程序执行的结果应该与代码顺序执行的结果一致(java编译器、
 *    运行时、处理器都会保证java在单线程下遵循as-if-serial 语义)
 *    
 * Volatile与synchronized比较
 *   volatile:不需要加锁，比synchronized更轻量级，不会阻塞线程，
 *      从内存可见性角度看，volatile进行读操作，好比是加锁，写
 *      操作是解锁
 * synchronized:即保证共享变量的可见性，又保证共享变量的原子性
 * 
 * 对64位Long,double的读写操作可能不是原子操作，java内存模型允许JVM将没有被
 *   volatile修饰的64位数据类型读写操作划分为两个32位的读写操作来进行
 * @author Administrator
 */
public class ThreaDemo {
	
	//共享变量
	private boolean ready = false;
	private int result = 0;
	private int number = 1;
	
	//write
	public void write() {
		ready = true;
		number += 1;
	}
	
	//read
	public void read () {
		if (ready)
			result = number * 3;
		System.out.printf("result = %d %n", result);
	}
	
	//内部线程类
	public class ReadWriteThread extends Thread {

		//根据构造方法传入的参数，确定执行read()还是write()
		private boolean flag = false;
		public ReadWriteThread(boolean flag) {
			this.flag = flag;
		}
		@Override
		public void run() {
			if (flag)
				write();
			else
				read();
		}
		
	}
}
